package labox.innovation.gameserver.util;

import java.util.List;
import java.util.Map;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javolution.util.FastList;
import javolution.util.FastMap;
import javolution.util.FastSet;
import labox.innovation.config.Config;
import labox.innovation.gameserver.datatables.NpcTemplateTable;
import labox.innovation.gameserver.idfactory.IdFactory;
import labox.innovation.gameserver.model.FuzeWorld;
import labox.innovation.gameserver.model.L2MinionData;
import labox.innovation.gameserver.model.Location;
import labox.innovation.gameserver.model.actor.instance.L2MinionInstance;
import labox.innovation.gameserver.model.actor.instance.FuzeMonsterInstance;
import labox.innovation.gameserver.templates.chars.NpcTemplate;
import labox.innovation.util.Rnd;

/**
 * 怪物的仆从对象列表管理器
 * 
 * @version $Revision: 1.2 $ $Date: 2004/06/27 08:12:59 $
 */

public final class MinionList {

	private static final Logger _log = LoggerFactory.getLogger(FuzeMonsterInstance.class.getName());

	/**
	 * 记录了当前出生的怪物仆从的列表
	 */
	private final List<L2MinionInstance> minionReferences;

	protected Map<Long, Integer> _respawnTasks = new FastMap<Long, Integer>();

	/**
	 * 拥有此怪物列表的主怪对象
	 */
	private final FuzeMonsterInstance master;

	/**
	 * 怪物的仆从对象列表管理器
	 * 
	 */
	public MinionList(FuzeMonsterInstance pMaster) {
		minionReferences = new FastList<L2MinionInstance>();
		master = pMaster;
	}

	/**
	 * 获得已出生的怪物仆从对象
	 * 
	 * @return
	 */
	public int countSpawnedMinions() {
		return minionReferences.size();
	}

	/**
	 * 获得某种类型的仆从对象的数量
	 * 
	 * @param minionId
	 * @return
	 */
	public int countSpawnedMinionsById(int minionId) {
		int count = 0;
		for (L2MinionInstance minion : minionReferences) {
			if (minion.getNpcId() == minionId) {
				count++;
			}
		}
		return count;
	}

	/**
	 * 返回是否拥有仆从对象
	 * 
	 * @return
	 */
	public boolean hasMinions() {
		return !getSpawnedMinions().isEmpty();
	}

	/**
	 * 获得管理的怪物列表
	 * 
	 * @return
	 */
	public List<L2MinionInstance> getSpawnedMinions() {
		return minionReferences;
	}

	/**
	 * 增加已出生的仆从
	 * 
	 * @param minion
	 */
	public void addSpawnedMinion(L2MinionInstance minion) {
		minionReferences.add(minion);
	}

	/**
	 * 返回管理的怪物的类型数量
	 * 
	 * @return
	 */
	public int lazyCountSpawnedMinionsGroups() {
		Set<Integer> seenGroups = new FastSet<Integer>();
		for (L2MinionInstance minion : minionReferences) {
			if (minion == null)
				continue;

			seenGroups.add(minion.getNpcId());
		}
		return seenGroups.size();
	}

	/**
	 * 删除一个管理的仆从
	 * 
	 * @param minion
	 */
	public void removeSpawnedMinion(L2MinionInstance minion) {
		minionReferences.remove(minion);
	}

	/**
	 * 把一个仆从放入待出生的任务管理器
	 * 
	 * @param minion
	 */
	public void moveMinionToRespawnList(L2MinionInstance minion) {
		Long current = System.currentTimeMillis();
		minionReferences.remove(minion);
		if (_respawnTasks.get(current) == null)
			_respawnTasks.put(current, minion.getNpcId());
		else {
			// nice AoE(Area of effect)
			//范围性作用技能(即在一定的范围内有效，可作用于多目标
			for (int i = 1; i < 30; i++) {
				if (_respawnTasks.get(current + i) == null) {
					_respawnTasks.put(current + i, minion.getNpcId());
					break;
				}
			}
		}
	}

	/**
	 * 清空待出生的任务管理器
	 */
	public void clearRespawnList() {
		_respawnTasks.clear();
	}

	/**
	 * 管理主怪的通过重生任务重生仆从<BR>
	 * <BR>
	 */
	public void maintainMinions() {
		if (master.isDead())
			return;
		long current = System.currentTimeMillis();
		if (_respawnTasks != null) {
			for (long deathTime : _respawnTasks.keySet()) {
				long delay = Config.RAID_MINION_RESPAWN_TIMER;
				if (current - deathTime > delay) {
					spawnSingleMinion(_respawnTasks.get(deathTime), master.getInstanceId());
					_respawnTasks.remove(deathTime);
				}
			}
		}

	}

	/**
	 * 管理主怪的所有仆从重生.<BR>
	 * <BR>
	 * 
	 * <B><U> Actions</U> :</B><BR>
	 * <BR>
	 * <li>Get the Minion data of all Minions that must be spawn</li> <li>For each Minion type, spawn the amount of Minion needed</li><BR>
	 * <BR>
	 * 
	 * @param player
	 *            The L2PcInstance to attack
	 * 
	 */
	public void spawnMinions() {
		if (master.isDead())
			return;
		List<L2MinionData> minions = master.getTemplate().getMinionData();

		if (minions == null)
			return;

		int minionCount, minionId, minionsToSpawn;
		for (L2MinionData minion : minions) {
			minionCount = minion.getAmount();//仆从的数量
			minionId = minion.getMinionId();//仆从的NPC模板ID

			//计算要出生的怪物的数量，最大的上限-目前的数量
			minionsToSpawn = minionCount - countSpawnedMinionsById(minionId);

			for (int i = 0; i < minionsToSpawn; i++) {
				spawnSingleMinion(minionId, master.getInstanceId());
			}
		}

	}

	/**
	 * Init a Minion and add it in the world as a visible object.<BR>
	 * <BR>
	 * 
	 * <B><U> Actions</U> :</B><BR>
	 * <BR>
	 * <li>Get the template of the Minion to spawn</li> <li>Create and Init the Minion and generate its Identifier</li> <li>Set the Minion HP, MP and Heading</li> <li>Set the Minion leader to this RaidBoss</li> <li>Init the position of the Minion and add it in the world as a visible object</li><BR>
	 * <BR>
	 * 
	 * @param minionid
	 *            需要出生的NPC模板ID
	 * @param instanceId
	 *            副本ID
	 * 
	 */
	public void spawnSingleMinion(int minionId, int instanceId) {
		// 获得要出生的怪物的模板ID
		NpcTemplate minionTemplate = NpcTemplateTable.getInstance().getTemplate(minionId);

		// 创建一个怪物仆从实例
		L2MinionInstance monster = new L2MinionInstance(IdFactory.getInstance().getNextId(IdFactory.ID_NPC), minionTemplate);

		// 设置仆从的HP和MP
		monster.setCurrentHpMp(monster.getMaxHp(), monster.getMaxMp());

		// 设置这个仆从的主怪
		monster.setLeader(master);

		//设置这个仆从的副本ID
		monster.setInstanceId(instanceId);
		
		monster.setName(minionTemplate.name);
		monster.setTitle(minionTemplate.title);

		// Init the position of the Minion and add it in the world as a visible object

		int randSpawnLim = 170;
		int newX = master.getX();
		newX += Rnd.get(-randSpawnLim, randSpawnLim);

		int newY = master.getY();
		newY += Rnd.get(-randSpawnLim, randSpawnLim);

		int sceneId = master.getScene().get_id();

		//检查碰撞问题
		Location loc = FuzeWorld.getInstance().getScene(sceneId).getGeoData().moveCheck(master.getX(), master.getY(), newX, newY);
		newX = loc.getX();
		newY = loc.getY();

		monster.reInitCharStatusUpdate();

		monster.spawnMe(sceneId, newX, newY);

		FuzeWorld.getInstance().enterWorld(monster);

		if (_log.isDebugEnabled())
			_log.debug("Spawned minion template " + minionTemplate._id + " with objid: " + monster.getObjectId() + " to boss " + master.getObjectId() + " ,at: " + monster.getX() + " x, " + monster.getY() + " y, ");
	}
}
